<?php
/*
 * Created on 05.03.2008
 *
 * filename: new_router.php5
 */
 
 /*
  * New implement of router
  * to find controller:
  * 1. try to get from "Controllers''
  * 2. try to get from "Plugins"
  * 3. try to find common partiton by aliases' chain
  * 4. if none of them found show index
  *   
  */
 
 class New_Router {
    private $registry;

    private $file;
    private $controller;
    private $action;
 	
    private $alias;
 	
    private $fineshed = false;

    private $args = array();
    private $url  = array();
 	
    private $common;
 	
    function __construct() {
        $this->common = new Common();
        // default arguments?
    }
 	
    // main method find sutible controller
    function delegate() {
 		
        // get requested url 		
        $route = (empty($_GET['route'])) ? 'index' : $_GET['route'];
        // cut last slash
        $route = trim($route, '/\\');

        if(!$this->fineshed){
// 			error_log("ROUTER: try to get controller");	
            $this->getController($route);
        }

        if(!$this->fineshed) {
// 			error_log("ROUTER: try to get plugin");
            $this->getPlugin($route);
        }

        if(!$this->fineshed) {
// 			error_log("ROUTER: try to get new plugin");
            $this->getNewPlugin($route);
        }

 			
 		if(!$this->fineshed) {
 			$this->getCommon($route);
// 			error_log("ROUTER: try to get from DB");
 		}
 			

//		if(!$this->fineshed)
//			$this->showIndex(); 			
 			
 			
 		if($this->fineshed) {

			try{
	 			include($this->file);
		
	 			$class = 'Controller_' . $this->controller;
	
	 			$controller = new $class();
				
				$action = $this->action;
	
	 			if(!is_callable(array($controller, $action))) {
					$this->args 	= array_merge(array($action), $this->args);
					$action 		= 'index';
		 		}
	 		
		 		$this->saveRouterTable();
				error_log("RUN: ".$class."->".$action."(file: $this->file, alias: $this->alias)" );
				error_log("ALIAS: $this->alias");
				$controller->setAlias($this->alias);
		 		
		 		// authomatic check access if method is callabe
		 		if(is_callable(array($controller, 'checkAccess'))) {
		 			$controller->checkAccess();
		 		}
		 		
		 		$result = $controller->$action($this->args);

			} catch (ControllerException $e) {
				error_log("ControllerException!: " . $e->getMessage() );
				// TODO make catch before without direct using 'header' 
                header(	"Location: ".$e->getLocation());
            }

            // set cookies
			if(isset($result) && $result->getCookies()) {
				foreach($result->getCookies() as $cookie) {
					setcookie($cookie[name], $cookie[value],$cookie[time],$cookie[path]);
				}
			}



            if(get_class($result) === 'Template') {
                // 
//print_r($result);                
                error_log("Returned: template");
                $result->setArg('route',$route);
                
                $result->setArg('_ROUTE',split('/',$route));

                // assign common data
                $result->setArg('_URL',$route);
                
		
                $this->common->assignCommon($result);
					
                $smarty = new Smarty_Construct();

				if ($result->path) {
					$smarty->template_dir = $result->path;
				}

                foreach($result->getAllArgs() as $key => $value) {
                    $smarty->assign($key,$value);
                }
		
				$smarty->assign('tmpl_path',site_path.'tmpl');
		
                if($result->getTemplate()) {
		 				
//                  $this->saveHtml('index.html',$this->registry['template']->fetch($result['template']->getTemplate()));	
		 			
                	$smarty->display($result->getTemplate());
                }
            } else if (get_class($result) === 'Redirect') {
                error_log("Returned: redirect");
                header('Location: '.$result->getLocation());
            } else if (get_class($result) === 'Plaintext') {
                error_log("Returned: plain text");
                if($result->getHeaders()) {
                    
                    foreach ($result->getHeaders() as $header ){
                        header($header);
                    }
                    
                    
                }
                echo $result->getText();
            } else {
                error_log("RESULT: ".serialize($result));                
            	error_log("Returned: something else");
//echo get_class($controller);
//                $smarty = new Smarty_Construct();   
            
//                header('Location: /error.html');
            }


		
 		}	
 		
 	}

 	// proxy method for finding controller
 	private function getController($route) {
 		$this->getSystemController($route,controllers_path);	
 	}

 	// proxy method for finding plugin 	
 	private function getPlugin($route) {
//echo " route0: $route <br />";
 		$this->getSystemController($route,plugins_path);
 	}


 	// proxy method for finding plugin 	
 	private function getNewPlugin($route) {
 		
//error_log(" ++ route:  $route");
 		preg_match("/(admin)\/(.*)/", $route, $match);
// print_r($match);
 		if ( $match[1] === 'admin' ) {
//echo "1<br>"; 			
 		
//print_r($match); 			

			$part = split("/",$match[0]);
//print_r($part);
 			$route = "$part[1]/admin"; // /$part[2]
 			$extra = $part[2];
//print_r($route);
 		} else {
//echo "2<br>";
 			$part = split("/",$route);
 			$route = $part[0];
 			$extra = $part[1];
 			
 			$args  = array_slice($part, 2);
 		}
//print_r($args);	
//error_log(" => $route /  $part[2] ");
//echo " route: $route extra: $extra args: $args<br />";

 		$this->getSystemController($route, plugins_path, array(new_plugin => 1, extra => $extra, args => $args));
 	}


	// method for finding controller class
 	private function getSystemController($route, $path, $args = null) {
 		$parts = explode('/',$route);

//print_r($parts);

		$new_plugin_controller = $parts[0];

 		$fullpath = $path;
 		$cmd_path = $fullpath;

 		while($parts) {
 			
				 			
			if(is_dir($cmd_path)) {
				$fullpath = $cmd_path;
				$cmd_path .= DIRSEP.$parts[0];	
//				$controller
	 		} else {
	 			break;
	 		}
	 		$controller = array_shift($parts);
 		}
//echo " path:  $cmd_path<br />"; 		
// 		$controller = array_shift($parts);
 		
// 		$controller = $controller ? $controller : 'index';

	 	$action = array_shift($parts);

 		
 		if($args[new_plugin]) {
 			$file =$fullpath.DIRSEP.$controller. ($action ? "/$action" :"/index" ).ext;
 		} else {
 			$file =$fullpath.DIRSEP.$controller.ext;
 		}
 	

//echo(" * file:  $file => action: $action <br />");	 	

	 	if(is_file($file)) {
	 		
//$this->registry['debug']->warn($file);	
//$this->registry['debug']->warn($controller);	 		
	 		
	 		if (!empty($action))
	 			$alias = $action;
	 		
	 		if (empty($alias))
	 		 	$alias = $controller;
	 		 	
	 		if (empty($alias))
	 		 	$alias = 'index';	 		

//print_r(array(
//	action 		=> $action,
//	controller 	=> $controller
//));

//print_r($parts);

			if(empty($action) && $args[new_plugin]) {
				$action = $args[extra];
			}

			$this->file			= $file;
			$this->controller 	= $args[new_plugin] ? $new_plugin_controller : $controller; 
//			$args[new_plugin] ? $parts[0] : 
			$this->args 		= $args[new_plugin] ? $args[args] : $parts;
			$this->action		= $action ? $action : 'index';
//			$this->alias		= $action ? $action : 'index';
			$this->alias		= $args[new_plugin] ? $new_plugin_controller : $alias;
			$this->fineshed	= 1;
	 	} 
 	}
 	
 	private function getCommon($route) {
		$menu 					= new Model_Menu($this->registry);
		$chain 					= explode('/',$route);
//$this->registry['debug']->warn($chain);
		$parent 				= array_shift($chain);

		// define 404 page url
		$redirect 				= $parent === 'admin' 
									? '/admin/' 
									: '/';

		if ($parent != 'admin')
			$this->url[] = $parent;


//$this->registry['debug']->warn($chain);

		$chain_reverse			= array_reverse($chain);
		$alias 					= $chain_reverse[0];

		$this->alias			= $alias ? $alias : $parent;
		
		if(empty($this->alias) || $this->alias === 'admin' )
			$this->alias 		= 'index';

//$this->registry['debug']->warn($this->alias);

		$this->args 			= $chain;

		$this->controller 		= 'index';
		$this->action			= 'index';

		$this->file = $parent 	=== 'admin' 
			? controllers_path.'/admin/index'.ext
			: controllers_path.'/index'.ext;

		if($parent === 'admin') 
			 $parent 			= empty($chain) ? 'index' : array_shift($chain);

//$this->registry['debug']->warn(array(parent => $parent));

		if (!$menu->checkParent('root', $parent)){
			header("Location: $redirect");
		}
		
		$new_url 		= "$parent/";

		while($chain) {
			$child 		= array_shift($chain);

			if (!$menu->checkParent($parent, $child)) {
				header("Location: $redirect$new_url");	
				break;	
			}
/*			
$this->registry['debug']->warn(array(
	parent	=> $parent,
	child	=> $child,		
	check 	=> $menu->checkParent($parent, $child)
));*/
			$new_url 	.= $child.'/';	
			$parent 	= $child;
		}

		$this->fineshed			= 1;	

 	}

	private function saveRouterTable() {
		$this->registry['router_table'] = array (
			alias 		=> $this->alias,
			url			=> $this->url
		);
	}
	
	private function saveHtml($filename,$html) {
		
		$filename=site_path."static/html/$filename";
		
		$handle = fopen($filename, "wb");
		$numbytes = fwrite($handle, $html);
	   	fclose($handle);
	   	error_log ("$numbytes bytes written to: $filename");		
	}
	
 	
  }
?>
